/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mobiwebinc.compconn.events;

import com.mobiwebinc.compconn.Main;
import com.mobiwebinc.compconn.communication.IOHandler;
import com.mobiwebinc.compconn.configuration.ClientConfiguration;
import com.mobiwebinc.compconn.configuration.Constant;
import com.mobiwebinc.compconn.events.command.Command;
import com.mobiwebinc.compconn.events.command.Decoder;
import com.mobiwebinc.compconn.screen.ScreenGeometry;
import com.mobiwebinc.compconn.screen.ScreenPackager;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author suraj
 */
public class Screen implements EventHandler {

    IOHandler io;
    ScreenPackager packager;
    ScreenGeometry geometry;
    ClientConfiguration clientConfiguration;
    static Image cursor = null;
    int lastSentImage = 0;
    int monitor = 0;
    final private static int CURSOR_WIDTH = 15, CURSOR_HEIGHT = 25;

    public Screen(IOHandler io, ScreenGeometry geometry) {
        this.io = io;
        this.packager = ScreenPackager.getInstance();
        packager.connected();
        this.geometry = geometry;
        this.clientConfiguration = geometry.getClientConfiguration();
    }

    public void handleRequest(String cmd) {
        if (cmd.startsWith(Command.SCREEN_SEND)) {
            sendScreen();
        } else if (cmd.startsWith(Command.SCREEN_RESET)) {
            resetScreen(cmd);
        } else if (cmd.startsWith(Command.SCREEN_PAN)) {
            pan(cmd);
        } else if (cmd.startsWith(Command.SCREEN_ZOOM)) {
            zoom(cmd);
        } else if (cmd.startsWith(Command.CLIENT_TERM)) {
            disconnected();
        } else if (cmd.startsWith(Command.SCREEN_SWITCH_MONITOR)) {
            switchMonitor(cmd);
        }
    }

    private void switchMonitor(String cmd) {
        int[] params = Decoder.intParameters(cmd);
        monitor = params[0];
        geometry.setMonitor(monitor);
        geometry.resetView();
    }

    private void drawCursor(Graphics g) throws HeadlessException {
        if (clientConfiguration.isCursorVisible()) {
            geometry.setScreenPt(MouseInfo.getPointerInfo().getLocation());
            g.drawImage(getCursor(), geometry.getPhonePt().x, geometry.getPhonePt().y, null);
        }
    }

    private void pan(String cmd) {
        int[] params = Decoder.intParameters(cmd);
        geometry.pan(new Point(params[0], params[1]));
    }

    private void resetScreen(String cmd) {
        int[] params = Decoder.intParameters(cmd);
        geometry.resetView(new Point(params[0], params[1]));
    }

    private void sendScreen() {
        Rectangle phoneInScreenRect = geometry.getPhoneInScreenRect();
        Image screenImage = getScreenShot().getSubimage(phoneInScreenRect.x, phoneInScreenRect.y, phoneInScreenRect.width, phoneInScreenRect.height).getScaledInstance(geometry.getPhoneRect().width, geometry.getPhoneRect().height, Image.SCALE_FAST);
        BufferedImage image = new BufferedImage(geometry.getPhoneRect().width + CURSOR_WIDTH, geometry.getPhoneRect().height + CURSOR_HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        g.drawImage(screenImage, geometry.getPhoneRect().x , geometry.getPhoneRect().y, null);
        drawCursor(g);
        io.sendImage((RenderedImage) image.getSubimage(0, 0, geometry.getPhoneRect().width, geometry.getPhoneRect().height));
    }

    private BufferedImage getScreenShot() {
        BufferedImage screen = packager.getScreen(monitor);
        while (screen == null) {
            holdIt();
            screen = packager.getScreen(monitor);
        }
        return screen;
    }

    private void zoom(String cmd) {
        double[] params = Decoder.doubleParameters(cmd);
        geometry.setZoom(params[0], params[1], params[2] * clientConfiguration.getZoomLevel());
    }

    private static Image getCursor() {
        if (cursor == null) {
            URL url = null;
            try {
                url = Main.class.getResource(Constant.CURSOR);
            } catch (Exception e) {
                System.out.println("icon image not found");
            }
            cursor = Toolkit.getDefaultToolkit().getImage(url);
        }
        return cursor;
    }

    public boolean isSupported(String cmd) {
        return cmd.startsWith(Command.SCREEN_PREFIX) || cmd.startsWith(Command.CLIENT_TERM);
    }

    private void disconnected() {
        packager.disconnected();
    }

    private void holdIt() {
        try {
            Thread.sleep(Constant.HOLD_TIME);
        } catch (InterruptedException ex) {
            Logger.getLogger(Screen.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
